package com.tm.seurity.config;

import com.tm.service.PermissionEvaluatorImpl;
import com.tm.service.UserDetailsServiceImpl;
import com.tm.seurity.filter.JwtAuthenticationTokenFilter;
import com.tm.seurity.handler.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;

import javax.annotation.Resource;

/**
 * Created by lichuan on 2022-09-24.
 */
@EnableWebSecurity
//开启权限注解,默认是关闭的
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    /**
     * 判断是否有访问权限的类
     */
    @Autowired
    private PermissionEvaluatorImpl permissionEvaluator;

    //查询用户信息
    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    /**
     * 用于处理无权限访问异常的类
     */
    @Autowired
    private AccessDeniedHandlerImpl accessDeniedHandler;

    //处理未登陆异常
    @Autowired
    private AuthenticationEntryPointImpl authenticationEntryPoint;

    /**
     * 登陆异常
     */
    @Resource
    private AuthenticationFailureHandlerImpl authenticationFailureHandler;

    /**
     * 登陆成功
     */
    @Autowired
    private AuthenticationSuccessHandlerImpl authenticationSuccessHandler;

    /**
     * 退出成功
     */
    @Resource
    private LogoutSuccessHandlerImpl logoutSuccessHandler ;


    /**
     * TODO 加密方式
     * @Author Sans
     * @CreateTime 2019/10/1 14:00
     */
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     * 注入自定义PermissionEvaluator
     */
    @Bean
    public DefaultWebSecurityExpressionHandler userSecurityExpressionHandler(){
        DefaultWebSecurityExpressionHandler handler = new DefaultWebSecurityExpressionHandler();
        handler.setPermissionEvaluator(permissionEvaluator);
        return handler;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                // 放行静态资源
                .antMatchers(
                        HttpMethod.GET,
                        "/*.html",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js",
                        "/webSocket/**"
                ).permitAll()
                // 放行swagger
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/*/api-docs").permitAll()
                // 放行文件访问
                .antMatchers("/file/**").permitAll()
                // 放行druid
                .antMatchers("/druid/**").permitAll()
                // 放行OPTIONS请求
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                //允许匿名及登录用户访问
                .antMatchers("/api/auth/**", "/error/**").permitAll()
                //其他的需要登录后才能访问
                .anyRequest().authenticated()
                .and()
                //配置登录地址
                .formLogin()
                .loginProcessingUrl("/login")
                //配置登录成功自定义处理类
                .successHandler(authenticationSuccessHandler)
                //配置登录失败自定义处理类
                .failureHandler(authenticationFailureHandler)
                .and()
                //配置登出地址
                .logout()
                .logoutUrl("/logout")
                //配置用户登出自定义处理类
                .logoutSuccessHandler(logoutSuccessHandler)
                .and()
                //配置没有权限自定义处理类
                .exceptionHandling().accessDeniedHandler(accessDeniedHandler)
                //配置未登录自定义处理类
                .authenticationEntryPoint(authenticationEntryPoint)
                .and()
                // 开启跨域
                .cors()
                .and()
                // 取消跨站请求伪造防护
                .csrf().disable();
        // 基于Token不需要session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        // 禁用缓存
        http.headers().cacheControl();
        // 添加JWT过滤器
        http.addFilter(new JwtAuthenticationTokenFilter(authenticationManager()));
    }
}
